/*      */ package com.zimbra.cs.imap;
/*      */ 
/*      */ import com.google.common.base.Function;
/*      */ import com.google.common.base.Strings;
/*      */ import com.google.common.collect.Iterators;
/*      */ import com.google.common.collect.Lists;
/*      */ import com.zimbra.client.ZFolder;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.soap.Element;
/*      */ import com.zimbra.common.util.ArrayUtil;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.Pair;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.cs.mailbox.Flag;
/*      */ import com.zimbra.cs.mailbox.Folder;
/*      */ import com.zimbra.cs.mailbox.MailItem;
/*      */ import com.zimbra.cs.mailbox.MailItem.Type;
/*      */ import com.zimbra.cs.mailbox.Mailbox;
/*      */ import com.zimbra.cs.mailbox.SearchFolder;
/*      */ import com.zimbra.cs.mailbox.Tag;
/*      */ import com.zimbra.cs.session.PendingModifications.Change;
/*      */ import com.zimbra.cs.session.Session;
/*      */ import com.zimbra.cs.session.Session.Type;
/*      */ import java.io.Serializable;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Arrays;
/*      */ import java.util.Collection;
/*      */ import java.util.Collections;
/*      */ import java.util.EnumSet;
/*      */ import java.util.HashMap;
/*      */ import java.util.Iterator;
/*      */ import java.util.LinkedList;
/*      */ import java.util.List;
/*      */ import java.util.ListIterator;
/*      */ import java.util.Map;
/*      */ import java.util.Set;
/*      */ import java.util.concurrent.ConcurrentSkipListMap;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public final class ImapFolder
/*      */   implements ImapSession.ImapFolderData, Serializable
/*      */ {
/*      */   private static final long serialVersionUID = 3845968507901145794L;
/*      */   static final byte SELECT_READONLY = 1;
/*      */   static final byte SELECT_CONDSTORE = 2;
/*      */   private transient Mailbox mailbox;
/*      */   private transient ImapSession session;
/*      */   private transient ImapPath path;
/*      */   private transient SessionData sessionData;
/*      */   private transient Map<Integer, ImapMessage> messageIds;
/*      */   private transient ImapFlagCache flags;
/*      */   private final int folderId;
/*      */   private final int uidValidity;
/*      */   private String query;
/*   75 */   private Set<MailItem.Type> typeConstraint = ImapHandler.ITEM_TYPES;
/*   76 */   private final List<ImapMessage> sequence = new ArrayList();
/*      */   
/*      */   private final ImapFlagCache tags;
/*      */   
/*      */ 
/*      */   static class SessionData
/*      */   {
/*      */     ImapCredentials credentials;
/*      */     boolean writable;
/*      */     int lastSize;
/*      */     int recentCount;
/*      */     int expungedCount;
/*      */     boolean tagsAreDirty;
/*      */     boolean notificationsSuspended;
/*      */     ImapMessage.ImapMessageSet savedSearchResults;
/*   91 */     final Map<Integer, ImapFolder.DirtyMessage> dirtyMessages = new ConcurrentSkipListMap();
/*      */     
/*      */     SessionData(ImapPath path, byte params, ImapHandler handler) throws ServiceException {
/*   94 */       this.credentials = handler.getCredentials();
/*   95 */       this.writable = (((params & 0x1) == 0) && (path.isWritable()));
/*      */     }
/*      */     
/*   98 */     boolean hasNotifications() { return (this.tagsAreDirty) || (!this.dirtyMessages.isEmpty()) || (this.expungedCount > 0); }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   ImapFolder(ImapPath path, byte params, ImapHandler handler)
/*      */     throws ServiceException
/*      */   {
/*  108 */     this.path = path;
/*  109 */     Folder folder = (Folder)path.getFolder();
/*  110 */     this.folderId = folder.getId();
/*      */     
/*  112 */     this.uidValidity = getUIDValidity(folder);
/*  113 */     if ((folder instanceof SearchFolder)) {
/*  114 */       this.query = ((SearchFolder)folder).getQuery();
/*  115 */       this.typeConstraint = getTypeConstraint((SearchFolder)folder);
/*      */     }
/*      */     
/*  118 */     if (handler != null) {
/*  119 */       this.sessionData = new SessionData(path, params, handler);
/*      */     }
/*  121 */     this.mailbox = folder.getMailbox();
/*  122 */     this.flags = ImapFlagCache.getSystemFlags(this.mailbox);
/*  123 */     this.tags = new ImapFlagCache();
/*      */   }
/*      */   
/*      */   void setInitialSize() {
/*  127 */     SessionData sdata = this.sessionData;
/*  128 */     if (sdata != null) {
/*  129 */       sdata.lastSize = this.sequence.size();
/*      */     }
/*      */   }
/*      */   
/*      */   public void doEncodeState(Element imap)
/*      */   {
/*  135 */     SessionData sdata = this.sessionData;
/*  136 */     if (sdata != null) {
/*  137 */       ImapCredentials.EnabledHack[] hacks = sdata.credentials.getEnabledHacks();
/*  138 */       imap.addAttribute("hack", hacks == null ? null : Arrays.toString(hacks));
/*  139 */       imap.addAttribute("writable", isWritable());
/*  140 */       imap.addAttribute("dirty", sdata.dirtyMessages.size()).addAttribute("expunged", sdata.expungedCount);
/*      */     }
/*  142 */     imap.addAttribute("size", getSize());
/*  143 */     imap.addAttribute("folder", this.path.asImapPath()).addAttribute("query", this.query);
/*      */   }
/*      */   
/*      */   void setSession(ImapSession value) {
/*  147 */     assert ((this.session == null) || (this.session == value) || (this.sessionData == null));
/*  148 */     this.session = value;
/*      */   }
/*      */   
/*      */   SessionData getSessionData() {
/*  152 */     return this.sessionData;
/*      */   }
/*      */   
/*      */   public void endSelect()
/*      */   {
/*  157 */     this.sessionData = null;
/*      */   }
/*      */   
/*      */   public Mailbox getMailbox()
/*      */   {
/*  162 */     return this.mailbox;
/*      */   }
/*      */   
/*      */ 
/*      */   ImapCredentials getCredentials()
/*      */   {
/*  168 */     SessionData sdata = this.sessionData;
/*  169 */     return sdata == null ? null : sdata.credentials;
/*      */   }
/*      */   
/*      */ 
/*      */   public int getId()
/*      */   {
/*  175 */     return this.folderId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public int getSize()
/*      */   {
/*  183 */     return this.sequence.size();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   int getRecentCount()
/*      */   {
/*  190 */     SessionData sdata = this.sessionData;
/*  191 */     return (isVirtual()) || (sdata == null) ? 0 : sdata.recentCount;
/*      */   }
/*      */   
/*      */   public boolean hasExpunges()
/*      */   {
/*  196 */     SessionData sdata = this.sessionData;
/*  197 */     return (sdata != null) && (sdata.expungedCount > 0);
/*      */   }
/*      */   
/*      */   public boolean hasNotifications()
/*      */   {
/*  202 */     SessionData sdata = this.sessionData;
/*  203 */     return (sdata != null) && (sdata.hasNotifications());
/*      */   }
/*      */   
/*      */ 
/*      */   String getQuery()
/*      */   {
/*  209 */     return Strings.nullToEmpty(this.query);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   static Set<MailItem.Type> getTypeConstraint(SearchFolder search)
/*      */   {
/*  216 */     String typestr = search.getReturnTypes().toLowerCase();
/*      */     Set<MailItem.Type> types;
/*  218 */     if (!typestr.isEmpty()) {
/*      */       try {
/*  220 */         types = MailItem.Type.setOf(typestr);
/*      */       } catch (IllegalArgumentException e) {
/*  222 */         ZimbraLog.imap.warn("invalid item type: " + typestr, e);
/*  223 */         return EnumSet.noneOf(MailItem.Type.class);
/*      */       }
/*      */     } else {
/*  226 */       types = EnumSet.of(MailItem.Type.CONVERSATION);
/*      */     }
/*      */     
/*  229 */     if (types.remove(MailItem.Type.CONVERSATION)) {
/*  230 */       types.add(MailItem.Type.MESSAGE);
/*      */     }
/*  232 */     types.retainAll(ImapMessage.SUPPORTED_TYPES);
/*  233 */     return types;
/*      */   }
/*      */   
/*      */ 
/*      */   Set<MailItem.Type> getTypeConstraint()
/*      */   {
/*  239 */     return this.typeConstraint;
/*      */   }
/*      */   
/*      */ 
/*      */   int getUIDValidity()
/*      */   {
/*  245 */     return this.uidValidity;
/*      */   }
/*      */   
/*      */   int getCurrentMODSEQ() throws ServiceException {
/*  249 */     return this.mailbox.getFolderById(null, this.folderId).getImapMODSEQ();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   boolean isVirtual()
/*      */   {
/*  256 */     return this.query != null;
/*      */   }
/*      */   
/*      */ 
/*      */   public boolean isWritable()
/*      */   {
/*  262 */     SessionData sdata = this.sessionData;
/*  263 */     return sdata == null ? false : sdata.writable;
/*      */   }
/*      */   
/*      */   public synchronized void traverse(Function<ImapMessage, Void> func) {
/*  267 */     int prevUid = -1;
/*  268 */     for (Iterator<ImapMessage> it = this.sequence.iterator(); it.hasNext();) {
/*  269 */       ImapMessage i4msg = (ImapMessage)it.next();
/*  270 */       if (i4msg.imapUid == prevUid) {
/*  271 */         ZimbraLog.imap.warn("duplicate UID %d in cached folder %d", new Object[] { Integer.valueOf(prevUid), Integer.valueOf(this.folderId) });
/*  272 */         it.remove();
/*      */       } else {
/*  274 */         prevUid = i4msg.imapUid;
/*  275 */         func.apply(i4msg);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   ImapPath getPath() {
/*  281 */     return this.path;
/*      */   }
/*      */   
/*      */   void updatePath(Folder folder) {
/*  285 */     this.path = new ImapPath(null, folder.getPath(), this.path.getCredentials());
/*      */   }
/*      */   
/*      */   String getQuotedPath() throws ServiceException {
/*  289 */     return '"' + this.path.asResolvedPath() + '"';
/*      */   }
/*      */   
/*      */   public String toString()
/*      */   {
/*  294 */     return this.path.toString();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   static int getUIDValidity(Folder folder)
/*      */   {
/*  301 */     return Math.max(folder.getSavedSequence(), 1);
/*      */   }
/*      */   
/*      */   static int getUIDValidity(ZFolder zfolder) {
/*  305 */     return zfolder.getContentSequence();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private int uidSearch(int uid)
/*      */   {
/*  321 */     int low = 0;int high = getSize() - 1;
/*  322 */     while (low <= high) {
/*  323 */       int mid = low + high >> 1;
/*  324 */       int targetUid = ((ImapMessage)this.sequence.get(mid)).imapUid;
/*  325 */       if (targetUid < uid) {
/*  326 */         low = mid + 1;
/*  327 */       } else if (targetUid > uid) {
/*  328 */         high = mid - 1;
/*      */       } else {
/*  330 */         return mid;
/*      */       }
/*      */     }
/*  333 */     return -(low + 1);
/*      */   }
/*      */   
/*      */ 
/*      */   synchronized ImapMessage getById(int id)
/*      */   {
/*  339 */     if ((id <= 0) || (getSize() == 0)) {
/*  340 */       return null;
/*      */     }
/*      */     
/*  343 */     int seq = uidSearch(id);
/*  344 */     if ((seq >= 0) && (seq < this.sequence.size())) {
/*  345 */       ImapMessage i4msg = (ImapMessage)this.sequence.get(seq);
/*      */       
/*      */ 
/*      */ 
/*  349 */       if ((i4msg != null) && (i4msg.msgId == id) && (!i4msg.isExpunged())) {
/*  350 */         return checkRemoved(i4msg);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  355 */     if (this.messageIds == null)
/*      */     {
/*  357 */       this.messageIds = new HashMap();
/*  358 */       for (ImapMessage i4msg : this.sequence) {
/*  359 */         if ((i4msg != null) && (i4msg.msgId != i4msg.imapUid)) {
/*  360 */           this.messageIds.put(Integer.valueOf(i4msg.msgId), i4msg);
/*      */         }
/*      */       }
/*      */     }
/*  364 */     return checkRemoved((ImapMessage)this.messageIds.get(Integer.valueOf(id)));
/*      */   }
/*      */   
/*      */ 
/*      */   ImapMessage getByImapId(int uid)
/*      */   {
/*  370 */     return uid > 0 ? getBySequence(uidSearch(uid) + 1) : null;
/*      */   }
/*      */   
/*      */ 
/*      */   ImapMessage getBySequence(int seq)
/*      */   {
/*  376 */     return getBySequence(seq, false);
/*      */   }
/*      */   
/*      */ 
/*      */   ImapMessage getBySequence(int seq, boolean includeExpunged)
/*      */   {
/*  382 */     ImapMessage i4msg = (seq > 0) && (seq <= getSize()) ? (ImapMessage)this.sequence.get(seq - 1) : null;
/*  383 */     return includeExpunged ? i4msg : checkRemoved(i4msg);
/*      */   }
/*      */   
/*      */ 
/*      */   private ImapMessage getLastMessage()
/*      */   {
/*  389 */     return getBySequence(getSize());
/*      */   }
/*      */   
/*      */ 
/*      */   private ImapMessage checkRemoved(ImapMessage i4msg)
/*      */   {
/*  395 */     return (i4msg == null) || (i4msg.isExpunged()) ? null : i4msg;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   synchronized boolean cache(ImapMessage i4msg, boolean recent)
/*      */   {
/*  405 */     if (this.folderId == 4) {
/*  406 */       ImapMessage tmp9_8 = i4msg;tmp9_8.sflags = ((short)(tmp9_8.sflags | 0xA));
/*      */     }
/*  408 */     if (recent) {
/*  409 */       ImapMessage tmp25_24 = i4msg;tmp25_24.sflags = ((short)(tmp25_24.sflags | 0x1));
/*  410 */       SessionData sdata = this.sessionData;
/*  411 */       if (sdata != null) {
/*  412 */         sdata.recentCount += 1;
/*      */       }
/*      */     }
/*      */     
/*  416 */     ImapMessage last = null;
/*  417 */     if ((this.sequence.size() > 0) && ((last = (ImapMessage)this.sequence.get(this.sequence.size() - 1)).imapUid > i4msg.imapUid)) {
/*  418 */       ZimbraLog.imap.debug("adding out of order UID. prev: %s current: %s", new Object[] { last, i4msg });
/*  419 */       if (!insertOutOfOrder(i4msg)) {
/*  420 */         return false;
/*      */       }
/*  422 */     } else if ((last != null) && (last.imapUid == i4msg.imapUid))
/*      */     {
/*  424 */       ZimbraLog.imap.warn("duplicate UID %s %s added to sequence", i4msg, last, new Exception());
/*  425 */       this.sequence.set(this.sequence.size() - 1, i4msg);
/*  426 */       setIndex(i4msg, this.sequence.size());
/*      */     }
/*      */     else {
/*  429 */       this.sequence.add(i4msg);
/*  430 */       setIndex(i4msg, this.sequence.size());
/*      */     }
/*      */     
/*  433 */     updateTagCache(i4msg);
/*  434 */     return true;
/*      */   }
/*      */   
/*      */   private boolean insertOutOfOrder(ImapMessage i4msg) {
/*  438 */     LinkedList<ImapMessage> shifted = new LinkedList();
/*  439 */     int idx = this.sequence.size() - 1;
/*  440 */     while (idx > -1) {
/*  441 */       ImapMessage prev = (ImapMessage)this.sequence.get(idx);
/*  442 */       if (prev.imapUid <= i4msg.imapUid)
/*      */         break;
/*  444 */       if (prev.isAdded()) {
/*  445 */         shifted.addFirst(prev);
/*      */         
/*      */ 
/*  448 */         idx--;
/*      */       } else {
/*  450 */         ZimbraLog.imap.warn("message added out of order occurs before message which is already visible to client. Must renumber %s", new Object[] { i4msg });
/*  451 */         this.session.incrementRenumber(i4msg);
/*  452 */         if (this.session.isFailedRenumber(i4msg)) {
/*  453 */           throw new ImapRenumberException();
/*      */         }
/*      */         
/*      */ 
/*  457 */         return false;
/*      */       }
/*      */     }
/*  460 */     idx++;
/*  461 */     this.sequence.add(idx, i4msg);
/*  462 */     setIndex(i4msg, idx + 1);
/*  463 */     for (ImapMessage shiftedMsg : shifted) {
/*  464 */       setIndex(shiftedMsg, shiftedMsg.sequence + 1);
/*      */     }
/*  466 */     return true;
/*      */   }
/*      */   
/*      */   void updateTagCache(ImapMessage i4msg) {
/*  470 */     if (!ArrayUtil.isEmpty(i4msg.tags)) {
/*  471 */       for (String tag : i4msg.tags) {
/*  472 */         if (this.tags.getByZimbraName(tag) == null) {
/*      */           try {
/*  474 */             this.tags.cache(new ImapFlagCache.ImapFlag(this.mailbox.getTagByName(null, tag)));
/*  475 */             setTagsDirty(true);
/*      */           } catch (ServiceException e) {
/*  477 */             ZimbraLog.imap.warn("could not fetch listed tag: %s", tag, e);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   private void setIndex(ImapMessage i4msg, int position) {
/*  485 */     i4msg.sequence = position;
/*  486 */     if (this.messageIds != null) {
/*  487 */       if (i4msg.msgId != i4msg.imapUid) {
/*  488 */         this.messageIds.put(Integer.valueOf(i4msg.msgId), i4msg);
/*      */       } else {
/*  490 */         this.messageIds.remove(Integer.valueOf(i4msg.msgId));
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private void uncache(ImapMessage i4msg)
/*      */   {
/*  499 */     if (this.messageIds != null) {
/*  500 */       this.messageIds.remove(Integer.valueOf(i4msg.msgId));
/*      */     }
/*  502 */     SessionData sdata = this.sessionData;
/*  503 */     if (sdata != null) {
/*  504 */       sdata.dirtyMessages.remove(Integer.valueOf(i4msg.imapUid));
/*  505 */       if ((i4msg.sflags & 0x1) != 0) {
/*  506 */         sdata.recentCount -= 1;
/*      */       }
/*  508 */       if ((i4msg.sflags & 0x200) != 0) {
/*  509 */         sdata.expungedCount -= 1;
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   boolean areTagsDirty() {
/*  515 */     SessionData sdata = this.sessionData;
/*  516 */     return sdata == null ? false : sdata.tagsAreDirty;
/*      */   }
/*      */   
/*      */   void setTagsDirty(boolean dirty) {
/*  520 */     SessionData sdata = this.sessionData;
/*  521 */     if (sdata != null) {
/*  522 */       sdata.tagsAreDirty = dirty;
/*      */     }
/*      */   }
/*      */   
/*      */   ImapFlagCache.ImapFlag cacheTag(Tag ltag) {
/*  527 */     assert (!(ltag instanceof Flag));
/*  528 */     if ((ltag instanceof Flag)) {
/*  529 */       return null;
/*      */     }
/*      */     
/*  532 */     setTagsDirty(true);
/*  533 */     return this.tags.cache(new ImapFlagCache.ImapFlag(ltag));
/*      */   }
/*      */   
/*      */   void dirtyTag(ImapFlagCache.ImapFlag i4flag, int modseq, String newName) {
/*  537 */     setTagsDirty(true);
/*  538 */     if ((getSize() == 0) || (i4flag == null)) {
/*  539 */       return;
/*      */     }
/*      */     
/*  542 */     for (ImapMessage i4msg : this.sequence) {
/*  543 */       if ((i4msg != null) && (i4flag.matches(i4msg))) {
/*  544 */         dirtyMessage(i4msg, modseq);
/*      */         
/*  546 */         List<String> tags = Lists.newArrayList(i4msg.tags);
/*  547 */         tags.remove(i4flag.mName);
/*  548 */         if (newName != null) {
/*  549 */           tags.add(newName);
/*      */         }
/*  551 */         i4msg.tags = (tags.isEmpty() ? null : (String[])tags.toArray(new String[tags.size()]));
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   ImapFlagCache.ImapFlag getFlagByName(String name) {
/*  557 */     ImapFlagCache.ImapFlag i4flag = this.flags.getByImapName(name);
/*  558 */     return i4flag != null ? i4flag : this.tags.getByImapName(name);
/*      */   }
/*      */   
/*      */   ImapFlagCache.ImapFlag getTagByName(String name) {
/*  562 */     return this.flags.getByImapName(name);
/*      */   }
/*      */   
/*      */   List<String> getFlagList(boolean permanentOnly) {
/*  566 */     List<String> names = this.flags.listNames(permanentOnly);
/*  567 */     for (String tagname : this.tags.listNames(permanentOnly)) {
/*  568 */       if (this.flags.getByImapName(tagname) == null) {
/*  569 */         names.add(tagname);
/*      */       }
/*      */     }
/*  572 */     return names;
/*      */   }
/*      */   
/*      */   ImapFlagCache getTagset() {
/*  576 */     return this.tags;
/*      */   }
/*      */   
/*      */ 
/*  580 */   void clearTagCache() { this.tags.clear(); }
/*      */   
/*      */   static final class DirtyMessage {
/*      */     ImapMessage i4msg;
/*      */     int modseq;
/*      */     
/*  586 */     DirtyMessage(ImapMessage m, int s) { this.i4msg = m;this.modseq = s;
/*      */     }
/*      */   }
/*      */   
/*  590 */   boolean isMessageDirty(ImapMessage i4msg) { SessionData sdata = this.sessionData;
/*  591 */     return sdata == null ? false : sdata.dirtyMessages.containsKey(Integer.valueOf(i4msg.imapUid));
/*      */   }
/*      */   
/*      */   void dirtyMessage(ImapMessage i4msg, int modseq) {
/*  595 */     SessionData sdata = this.sessionData;
/*  596 */     if (sdata == null) {
/*  597 */       return;
/*      */     }
/*  599 */     if ((sdata.notificationsSuspended) || (i4msg != getBySequence(i4msg.sequence))) {
/*  600 */       return;
/*      */     }
/*  602 */     DirtyMessage dirty = (DirtyMessage)sdata.dirtyMessages.get(Integer.valueOf(i4msg.imapUid));
/*  603 */     if (dirty == null) {
/*  604 */       sdata.dirtyMessages.put(Integer.valueOf(i4msg.imapUid), new DirtyMessage(i4msg, modseq));
/*  605 */     } else if (modseq > dirty.modseq) {
/*  606 */       dirty.modseq = modseq;
/*      */     }
/*      */   }
/*      */   
/*      */   DirtyMessage undirtyMessage(ImapMessage i4msg) {
/*  611 */     SessionData sdata = this.sessionData;
/*  612 */     if (sdata == null) {
/*  613 */       return null;
/*      */     }
/*  615 */     DirtyMessage dirty = (DirtyMessage)sdata.dirtyMessages.remove(Integer.valueOf(i4msg.imapUid));
/*  616 */     if (dirty != null) {
/*  617 */       dirty.i4msg.setAdded(false);
/*      */     }
/*  619 */     return dirty;
/*      */   }
/*      */   
/*      */   Iterator<DirtyMessage> dirtyIterator() {
/*  623 */     SessionData sdata = this.sessionData;
/*  624 */     return sdata == null ? Iterators.emptyIterator() : sdata.dirtyMessages.values().iterator();
/*      */   }
/*      */   
/*      */   void clearDirty()
/*      */   {
/*  629 */     SessionData sdata = this.sessionData;
/*  630 */     if (sdata != null) {
/*  631 */       sdata.dirtyMessages.clear();
/*      */     }
/*      */   }
/*      */   
/*      */   boolean checkpointSize() {
/*  636 */     SessionData sdata = this.sessionData;
/*  637 */     if (sdata == null) {
/*  638 */       return false;
/*      */     }
/*  640 */     int last = sdata.lastSize;
/*  641 */     return last != (sdata.lastSize = getSize());
/*      */   }
/*      */   
/*      */   void disableNotifications() {
/*  645 */     SessionData sdata = this.sessionData;
/*  646 */     if (sdata != null) {
/*  647 */       sdata.notificationsSuspended = true;
/*      */     }
/*      */   }
/*      */   
/*      */   void enableNotifications() {
/*  652 */     SessionData sdata = this.sessionData;
/*  653 */     if (sdata != null) {
/*  654 */       sdata.notificationsSuspended = false;
/*      */     }
/*      */   }
/*      */   
/*      */   void saveSearchResults(ImapMessage.ImapMessageSet i4set) {
/*  659 */     SessionData sdata = this.sessionData;
/*  660 */     if (sdata != null) {
/*  661 */       i4set.remove(null);
/*  662 */       sdata.savedSearchResults = i4set;
/*      */     }
/*      */   }
/*      */   
/*      */   ImapMessage.ImapMessageSet getSavedSearchResults() {
/*  667 */     SessionData sdata = this.sessionData;
/*  668 */     if (sdata == null) {
/*  669 */       return new ImapMessage.ImapMessageSet();
/*      */     }
/*  671 */     if (sdata.savedSearchResults == null) {
/*  672 */       sdata.savedSearchResults = new ImapMessage.ImapMessageSet();
/*      */     }
/*  674 */     return sdata.savedSearchResults;
/*      */   }
/*      */   
/*      */   void markMessageExpunged(ImapMessage i4msg) {
/*  678 */     if (i4msg.isExpunged()) {
/*  679 */       return;
/*      */     }
/*  681 */     i4msg.setExpunged(true);
/*      */     
/*  683 */     SessionData sdata = this.sessionData;
/*  684 */     if (sdata != null) {
/*  685 */       if (sdata.savedSearchResults != null) {
/*  686 */         sdata.savedSearchResults.remove(i4msg);
/*      */       }
/*  688 */       sdata.expungedCount += 1;
/*      */     }
/*      */   }
/*      */   
/*      */   synchronized ImapMessage.ImapMessageSet getAllMessages() {
/*  693 */     ImapMessage.ImapMessageSet result = new ImapMessage.ImapMessageSet();
/*  694 */     if (getSize() > 0) {
/*  695 */       result.addAll(this.sequence);
/*  696 */       result.remove(null);
/*      */     }
/*  698 */     return result;
/*      */   }
/*      */   
/*      */   synchronized ImapMessage.ImapMessageSet getFlaggedMessages(ImapFlagCache.ImapFlag i4flag) {
/*  702 */     ImapMessage.ImapMessageSet result = new ImapMessage.ImapMessageSet();
/*  703 */     if ((i4flag != null) && (getSize() > 0)) {
/*  704 */       for (ImapMessage i4msg : this.sequence) {
/*  705 */         if ((i4msg != null) && (i4flag.matches(i4msg))) {
/*  706 */           result.add(i4msg);
/*      */         }
/*      */       }
/*      */     }
/*  710 */     return result;
/*      */   }
/*      */   
/*      */   private static int parseId(String id)
/*      */   {
/*      */     try {
/*  716 */       return (int)Math.max(-1L, Math.min(2147483647L, Long.parseLong(id)));
/*      */     } catch (NumberFormatException nfe) {}
/*  718 */     return Integer.MAX_VALUE;
/*      */   }
/*      */   
/*      */   private List<Pair<Integer, Integer>> normalizeSubsequence(String subseqStr, boolean byUID)
/*      */   {
/*  723 */     if ((subseqStr == null) || (subseqStr.trim().isEmpty())) {
/*  724 */       return Collections.emptyList();
/*      */     }
/*  726 */     ImapMessage i4msg = getLastMessage();
/*  727 */     int lastID = byUID ? i4msg.imapUid : i4msg == null ? getSize() : byUID ? Integer.MAX_VALUE : i4msg.sequence;
/*      */     
/*  729 */     List<Pair<Integer, Integer>> normalized = new ArrayList(5);
/*  730 */     for (String subset : subseqStr.split(",")) { int lower;
/*      */       int lower;
/*  732 */       int upper; if (subset.indexOf(':') == -1) {
/*      */         int upper;
/*  734 */         lower = upper = subset.equals("*") ? lastID : parseId(subset);
/*      */       }
/*      */       else {
/*  737 */         String[] range = subset.split(":", 2);
/*  738 */         lower = range[0].equals("*") ? lastID : parseId(range[0]);
/*  739 */         upper = range[1].equals("*") ? lastID : parseId(range[1]);
/*  740 */         if (lower > upper) {
/*  741 */           int tmp = upper;
/*  742 */           upper = lower;
/*  743 */           lower = tmp;
/*      */         }
/*      */       }
/*      */       
/*      */ 
/*  748 */       int insertpos = 0;
/*  749 */       for (int i = 0; i < normalized.size(); i++) {
/*  750 */         Pair<Integer, Integer> range = (Pair)normalized.get(i);
/*  751 */         int lrange = ((Integer)range.getFirst()).intValue();int urange = ((Integer)range.getSecond()).intValue();
/*  752 */         if (lower > urange + 1) {
/*  753 */           insertpos++;
/*      */         } else {
/*  755 */           if (upper < lrange - 1) {
/*      */             break;
/*      */           }
/*  758 */           normalized.remove(i--);
/*  759 */           lower = Math.min(lower, lrange);upper = Math.max(upper, urange);
/*      */         }
/*      */       }
/*  762 */       normalized.add(insertpos, new Pair(Integer.valueOf(lower), Integer.valueOf(upper)));
/*      */     }
/*  764 */     return normalized;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   static class SubSequenceRanges
/*      */   {
/*      */     List<Pair<Integer, Integer>> ranges;
/*      */     
/*  773 */     int rangeIndex = 0;
/*  774 */     int nextNum = 0;
/*      */     
/*      */ 
/*      */ 
/*      */     SubSequenceRanges(List<Pair<Integer, Integer>> theRanges)
/*      */     {
/*  780 */       this.ranges = theRanges;
/*  781 */       if (!this.ranges.isEmpty()) {
/*  782 */         this.nextNum = ((Integer)((Pair)this.ranges.get(this.rangeIndex)).getFirst()).intValue();
/*      */       }
/*      */     }
/*      */     
/*      */     boolean hasNext() {
/*  787 */       return (this.rangeIndex < this.ranges.size()) && (this.nextNum <= ((Integer)((Pair)this.ranges.get(this.rangeIndex)).getSecond()).intValue());
/*      */     }
/*      */     
/*      */     int next()
/*      */     {
/*  792 */       int retVal = this.nextNum;
/*  793 */       if (this.nextNum < ((Integer)((Pair)this.ranges.get(this.rangeIndex)).getSecond()).intValue()) {
/*  794 */         this.nextNum += 1;
/*      */       } else {
/*  796 */         this.rangeIndex += 1;
/*  797 */         if (this.rangeIndex < this.ranges.size()) {
/*  798 */           this.nextNum = ((Integer)((Pair)this.ranges.get(this.rangeIndex)).getFirst()).intValue();
/*      */         }
/*      */       }
/*  801 */       return retVal;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   int getSequenceMatchDataLowWater(String tag, String seqMilestones, String uidMilestones)
/*      */     throws ImapParseException
/*      */   {
/*  825 */     int lowwater = 1;
/*  826 */     if ((seqMilestones == null) || (seqMilestones.trim().isEmpty()) || (uidMilestones == null) || (uidMilestones.trim().isEmpty()))
/*      */     {
/*      */ 
/*      */ 
/*  830 */       return lowwater;
/*      */     }
/*      */     
/*  833 */     SubSequenceRanges seqRanges = new SubSequenceRanges(normalizeSubsequence(seqMilestones, false));
/*  834 */     SubSequenceRanges uidRanges = new SubSequenceRanges(normalizeSubsequence(uidMilestones, true));
/*  835 */     while (seqRanges.hasNext()) {
/*  836 */       int currSeq = seqRanges.next();
/*  837 */       if (currSeq < 1) {
/*  838 */         throw new ImapParseException(tag, String.format("invalid message sequence number: %s", new Object[] { seqMilestones }));
/*      */       }
/*  840 */       if (!uidRanges.hasNext()) break;
/*  841 */       int currUid = uidRanges.next();
/*  842 */       ImapMessage i4msgBySeq = getBySequence(currSeq, false);
/*  843 */       ImapMessage i4msgByUid = getByImapId(currUid);
/*  844 */       if ((i4msgByUid == null) || (i4msgByUid != i4msgBySeq)) {
/*      */         break;
/*      */       }
/*      */       
/*  848 */       lowwater = i4msgByUid.imapUid + 1;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*  854 */     return lowwater;
/*      */   }
/*      */   
/*      */   ImapMessage.ImapMessageSet getSubsequence(String tag, String subseqStr, boolean byUID) throws ImapParseException {
/*  858 */     return getSubsequence(tag, subseqStr, byUID, false);
/*      */   }
/*      */   
/*      */   ImapMessage.ImapMessageSet getSubsequence(String tag, String subseqStr, boolean byUID, boolean allowOutOfRangeMsgSeq) throws ImapParseException
/*      */   {
/*  863 */     return getSubsequence(tag, subseqStr, byUID, allowOutOfRangeMsgSeq, false);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   ImapMessage.ImapMessageSet getSubsequence(String tag, String subseqStr, boolean byUID, boolean allowOutOfRangeMsgSeq, boolean includeExpunged)
/*      */     throws ImapParseException
/*      */   {
/*  874 */     ImapMessage.ImapMessageSet result = new ImapMessage.ImapMessageSet();
/*  875 */     if ((subseqStr == null) || (subseqStr.trim().isEmpty()))
/*  876 */       return result;
/*  877 */     if (subseqStr.equals("$")) {
/*  878 */       return getSavedSearchResults();
/*      */     }
/*  880 */     for (Pair<Integer, Integer> range : normalizeSubsequence(subseqStr, byUID)) {
/*  881 */       int lower = ((Integer)range.getFirst()).intValue();int upper = ((Integer)range.getSecond()).intValue();
/*  882 */       if ((!byUID) && (!allowOutOfRangeMsgSeq) && ((lower < 1) || (upper > getSize())))
/*      */       {
/*      */ 
/*      */ 
/*  886 */         throw new ImapParseException(tag, "invalid message sequence number: " + subseqStr); }
/*  887 */       if (lower == upper)
/*      */       {
/*  889 */         result.add(byUID ? getByImapId(lower) : getBySequence(lower, includeExpunged));
/*      */ 
/*      */       }
/*  892 */       else if (!byUID) {
/*  893 */         upper = Math.min(getSize(), upper);
/*  894 */         for (int seq = Math.max(0, lower); seq <= upper; seq++) {
/*  895 */           result.add(getBySequence(seq, includeExpunged));
/*      */         }
/*      */       }
/*      */       else {
/*  899 */         int start = uidSearch(lower);int end = uidSearch(upper);
/*  900 */         if (start < 0) {
/*  901 */           start = -start - 1;
/*      */         }
/*  903 */         if (end < 0) {
/*  904 */           end = -end - 2;
/*      */         }
/*  906 */         for (int seq = start; seq <= end; seq++) { ImapMessage i4msg;
/*  907 */           if ((i4msg = getBySequence(seq + 1)) != null) {
/*  908 */             result.add(i4msg);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  915 */     return result;
/*      */   }
/*      */   
/*      */   String cropSubsequence(String subseqStr, boolean byUID, int croplow, int crophigh) {
/*  919 */     if ((croplow <= 0) && (crophigh <= 0)) {
/*  920 */       return subseqStr;
/*      */     }
/*  922 */     StringBuilder sb = new StringBuilder(subseqStr.length());
/*  923 */     for (Pair<Integer, Integer> range : normalizeSubsequence(subseqStr, byUID)) {
/*  924 */       int lower = ((Integer)range.getFirst()).intValue();int upper = ((Integer)range.getSecond()).intValue();
/*  925 */       if (((croplow <= 0) || (upper >= croplow)) && (
/*      */       
/*      */ 
/*  928 */         (crophigh <= 0) || (lower <= crophigh)))
/*      */       {
/*      */ 
/*  931 */         if (croplow > 0) {
/*  932 */           lower = Math.max(lower, croplow);
/*      */         }
/*  934 */         if (crophigh > 0) {
/*  935 */           upper = Math.min(upper, crophigh);
/*      */         }
/*  937 */         sb.append(sb.length() == 0 ? "" : ",").append(lower).append(":" + upper);
/*      */       } }
/*  939 */     return sb.toString();
/*      */   }
/*      */   
/*      */   String invertSubsequence(String subseqStr, boolean byUID, Set<ImapMessage> i4set) {
/*  943 */     StringBuilder sb = new StringBuilder();
/*      */     
/*  945 */     Iterator<ImapMessage> i4it = i4set.iterator();
/*  946 */     Iterator<Pair<Integer, Integer>> itrange = normalizeSubsequence(subseqStr, byUID).iterator();
/*  947 */     if (!itrange.hasNext()) {
/*  948 */       return subseqStr;
/*      */     }
/*  950 */     Pair<Integer, Integer> range = (Pair)itrange.next();
/*  951 */     int lower = ((Integer)range.getFirst()).intValue();
/*  952 */     int upper = ((Integer)range.getSecond()).intValue();
/*  953 */     int id = byUID ? ((ImapMessage)i4it.next()).imapUid : !i4it.hasNext() ? -1 : ((ImapMessage)i4it.next()).sequence;
/*      */     
/*  955 */     while (lower != -1) {
/*  956 */       if (lower > upper)
/*      */       {
/*  958 */         if (!itrange.hasNext()) {
/*      */           break;
/*      */         }
/*  961 */         range = (Pair)itrange.next();
/*  962 */         lower = ((Integer)range.getFirst()).intValue();
/*  963 */         upper = ((Integer)range.getSecond()).intValue();
/*  964 */       } else if ((id == -1) || (id > upper))
/*      */       {
/*  966 */         sb.append(sb.length() == 0 ? "" : ",").append(lower).append(":" + upper);
/*  967 */         if (!itrange.hasNext()) {
/*      */           break;
/*      */         }
/*  970 */         range = (Pair)itrange.next();lower = ((Integer)range.getFirst()).intValue();upper = ((Integer)range.getSecond()).intValue();
/*  971 */       } else if (id <= lower)
/*      */       {
/*  973 */         if (id == lower) {
/*  974 */           lower++;
/*      */         }
/*  976 */         id = byUID ? ((ImapMessage)i4it.next()).imapUid : !i4it.hasNext() ? -1 : ((ImapMessage)i4it.next()).sequence;
/*      */       }
/*      */       else {
/*  979 */         sb.append(sb.length() == 0 ? "" : ",").append(lower).append(":" + (id - 1));
/*  980 */         lower = id + 1;
/*  981 */         id = byUID ? ((ImapMessage)i4it.next()).imapUid : !i4it.hasNext() ? -1 : ((ImapMessage)i4it.next()).sequence;
/*      */       }
/*      */     }
/*  984 */     return sb.toString();
/*      */   }
/*      */   
/*      */   static String encodeSubsequence(List<Integer> items) {
/*  988 */     if ((items == null) || (items.isEmpty())) {
/*  989 */       return "";
/*      */     }
/*      */     
/*  992 */     StringBuilder sb = new StringBuilder();
/*  993 */     int start = -1;int last = -1;
/*      */     
/*  995 */     Iterator<Integer> it = items.iterator();
/*      */     boolean done;
/*  997 */     do { done = !it.hasNext();
/*  998 */       int next = done ? -1 : ((Integer)it.next()).intValue();
/*  999 */       if (last == -1) {
/* 1000 */         last = start = next;
/* 1001 */       } else if ((done) || (next != last + 1)) {
/* 1002 */         if (sb.length() > 0) {
/* 1003 */           sb.append(',');
/*      */         }
/* 1005 */         sb.append(start);
/* 1006 */         if (start != last) {
/* 1007 */           sb.append(':').append(last);
/*      */         }
/* 1009 */         last = start = next;
/*      */       } else {
/* 1011 */         last = next;
/*      */       }
/* 1013 */     } while (!done);
/* 1014 */     return sb.toString();
/*      */   }
/*      */   
/*      */   static String encodeSubsequence(Collection<ImapMessage> items, boolean byUID) {
/* 1018 */     if ((items == null) || (items.isEmpty())) {
/* 1019 */       return "";
/*      */     }
/*      */     
/* 1022 */     StringBuilder sb = new StringBuilder();
/* 1023 */     int start = -1;int last = -1;
/*      */     
/* 1025 */     Iterator<ImapMessage> it = items.iterator();
/*      */     boolean done;
/* 1027 */     do { done = !it.hasNext();
/* 1028 */       int next = byUID ? ((ImapMessage)it.next()).imapUid : done ? -1 : ((ImapMessage)it.next()).sequence;
/* 1029 */       if (last == -1) {
/* 1030 */         last = start = next;
/* 1031 */       } else if ((done) || (next != last + 1)) {
/* 1032 */         if (sb.length() > 0) {
/* 1033 */           sb.append(',');
/*      */         }
/* 1035 */         sb.append(start);
/* 1036 */         if (start != last) {
/* 1037 */           sb.append(':').append(last);
/*      */         }
/* 1039 */         last = start = next;
/*      */       } else {
/* 1041 */         last = next;
/*      */       }
/* 1043 */     } while (!done);
/* 1044 */     return sb.toString();
/*      */   }
/*      */   
/*      */   synchronized List<Integer> collapseExpunged(boolean byUID) {
/* 1048 */     if (getSize() == 0) {
/* 1049 */       return Collections.emptyList();
/*      */     }
/* 1051 */     ZimbraLog.imap.debug("  ** iterating (collapseExpunged)");
/*      */     
/* 1053 */     boolean trimmed = false;
/* 1054 */     int seq = 1;
/* 1055 */     List<Integer> removed = new ArrayList();
/* 1056 */     for (ListIterator<ImapMessage> lit = this.sequence.listIterator(); lit.hasNext(); seq++) {
/* 1057 */       ImapMessage i4msg = (ImapMessage)lit.next();
/* 1058 */       if (i4msg.isExpunged()) {
/* 1059 */         ZimbraLog.imap.debug("  ** removing: %s", new Object[] { i4msg });
/*      */         
/*      */ 
/*      */ 
/* 1063 */         uncache(i4msg);
/* 1064 */         lit.remove();
/*      */         
/* 1066 */         if (!i4msg.isAdded()) {
/* 1067 */           removed.add(Integer.valueOf(byUID ? i4msg.imapUid : seq));
/*      */         }
/* 1069 */         seq--;
/* 1070 */         trimmed = true;
/* 1071 */       } else if (trimmed) {
/* 1072 */         setIndex(i4msg, seq);
/*      */       }
/*      */     }
/* 1075 */     return removed;
/*      */   }
/*      */   
/*      */   void restore(ImapSession sess, SessionData sdata) throws ImapSessionClosedException, ServiceException {
/* 1079 */     this.session = sess;
/* 1080 */     this.mailbox = this.session.getMailbox();
/* 1081 */     if (this.mailbox == null) {
/* 1082 */       throw new ImapSessionClosedException();
/*      */     }
/* 1084 */     this.path = this.session.getPath();
/* 1085 */     this.flags = ImapFlagCache.getSystemFlags(this.mailbox);
/*      */     
/* 1087 */     this.sessionData = sdata;
/*      */   }
/*      */   
/*      */   public void handleTagDelete(int changeId, int tagId, PendingModifications.Change chg)
/*      */   {
/* 1092 */     dirtyTag(this.tags.uncache(tagId), changeId, null);
/*      */   }
/*      */   
/*      */   public void handleTagRename(int changeId, Tag tag, PendingModifications.Change chg)
/*      */   {
/* 1097 */     dirtyTag(this.tags.uncache(tag.getId()), changeId, tag.getName());
/* 1098 */     cacheTag(tag);
/*      */   }
/*      */   
/*      */   public void handleItemDelete(int changeId, int itemId, PendingModifications.Change chg)
/*      */   {
/* 1103 */     ImapMessage i4msg = getById(itemId);
/* 1104 */     if (i4msg != null) {
/* 1105 */       markMessageExpunged(i4msg);
/* 1106 */       ZimbraLog.imap.debug("  ** deleted (ntfn): %d", new Object[] { Integer.valueOf(i4msg.msgId) });
/*      */     }
/*      */   }
/*      */   
/*      */   public void handleItemCreate(int changeId, MailItem item, ImapSession.AddedItems added)
/*      */   {
/* 1112 */     int msgId = item.getId();
/*      */     
/* 1114 */     if (getById(msgId) != null) {
/* 1115 */       return;
/*      */     }
/*      */     
/* 1118 */     ImapMessage i4msg = getByImapId(item.getImapUid());
/* 1119 */     if (i4msg == null) {
/* 1120 */       added.add(item);
/*      */     }
/* 1122 */     ZimbraLog.imap.debug("  ** created (ntfn): %d", new Object[] { Integer.valueOf(msgId) });
/*      */   }
/*      */   
/*      */   public void handleFolderRename(int changeId, Folder folder, PendingModifications.Change chg)
/*      */   {
/* 1127 */     updatePath(folder);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void handleItemUpdate(int changeId, PendingModifications.Change chg, ImapSession.AddedItems added)
/*      */   {
/* 1136 */     MailItem item = (MailItem)chg.what;
/* 1137 */     boolean inFolder = (isVirtual()) || (item.getFolderId() == this.folderId);
/*      */     
/* 1139 */     ImapMessage i4msg = getById(item.getId());
/* 1140 */     if (i4msg == null) {
/* 1141 */       if ((inFolder) && (!isVirtual())) {
/* 1142 */         added.add(item);
/* 1143 */         ZimbraLog.imap.debug("  ** moved (ntfn) {id: %d UID: %d}", new Object[] { Integer.valueOf(item.getId()), Integer.valueOf(item.getImapUid()) });
/*      */       }
/* 1145 */     } else if ((!inFolder) && (!isVirtual())) {
/* 1146 */       markMessageExpunged(i4msg);
/* 1147 */     } else if ((chg.why & 0x80) != 0)
/*      */     {
/* 1149 */       if ((item.getImapUid() > 0) && (i4msg.imapUid > item.getImapUid()))
/*      */       {
/*      */ 
/* 1152 */         ZimbraLog.imap.debug("IMAP UID changed (ntfn) {id: %d UID: %d} but sequence already contains higher UID %s", new Object[] { Integer.valueOf(item.getId()), Integer.valueOf(item.getImapUid()), i4msg });
/* 1153 */         return;
/*      */       }
/* 1155 */       markMessageExpunged(i4msg);
/* 1156 */       if (!isVirtual()) {
/* 1157 */         added.add(item);
/*      */       }
/* 1159 */       ZimbraLog.imap.debug("  ** imap uid changed (ntfn) {id: %d UID: %d}", new Object[] { Integer.valueOf(item.getId()), Integer.valueOf(item.getImapUid()) });
/* 1160 */     } else if ((chg.why & 0x7) != 0) {
/* 1161 */       i4msg.setPermanentFlags(item.getFlagBitmask(), item.getTags(), changeId, this);
/*      */     }
/*      */   }
/*      */   
/*      */   public void handleAddedMessages(int changeId, ImapSession.AddedItems added)
/*      */   {
/* 1167 */     boolean debug = ZimbraLog.imap.isDebugEnabled();
/*      */     
/* 1169 */     added.sort();
/* 1170 */     boolean recent = true;
/* 1171 */     for (Session s : this.mailbox.getListeners(Session.Type.IMAP))
/*      */     {
/* 1173 */       ImapSession i4session = (ImapSession)s;
/* 1174 */       if (i4session == this.session)
/*      */         break;
/* 1176 */       if ((i4session.isWritable()) && (i4session.getFolderId() == this.folderId)) {
/* 1177 */         recent = false;
/* 1178 */         break;
/*      */       }
/*      */     }
/*      */     
/* 1182 */     List<Integer> renumber = new ArrayList();
/*      */     
/* 1184 */     if (added.numbered != null)
/*      */     {
/* 1186 */       StringBuilder addlog = debug ? new StringBuilder("  ** adding messages (ntfn) ") : null;
/* 1187 */       for (ImapMessage i4msg : added.numbered) {
/* 1188 */         if (cache(i4msg, recent)) {
/* 1189 */           if (debug) {
/* 1190 */             addlog.append(i4msg).append(' ');
/*      */           }
/* 1192 */           i4msg.setAdded(true);
/* 1193 */           dirtyMessage(i4msg, changeId);
/*      */         } else {
/* 1195 */           renumber.add(Integer.valueOf(i4msg.msgId));
/*      */         }
/*      */       }
/* 1198 */       if (debug) {
/* 1199 */         ZimbraLog.imap.debug(addlog);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/* 1204 */     if ((added.unnumbered != null) || (renumber.size() > 0))
/*      */     {
/*      */ 
/*      */ 
/* 1208 */       if (added.unnumbered != null) {
/* 1209 */         for (ImapMessage i4msg : added.unnumbered) {
/* 1210 */           renumber.add(Integer.valueOf(i4msg.msgId));
/*      */         }
/*      */       }
/*      */       try {
/* 1214 */         ZimbraLog.imap.debug("  ** moved; changing imap uid (ntfn): %s", new Object[] { renumber });
/*      */         
/* 1216 */         getMailbox().resetImapUid(null, renumber);
/*      */       } catch (ServiceException e) {
/* 1218 */         if (debug) {
/* 1219 */           ZimbraLog.imap.debug("  ** moved; imap uid change failed; msg hidden (ntfn): %s", new Object[] { renumber });
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   public void finishNotification(int changeId) {}
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/ImapFolder.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */